

#include "config.h"
#include "env.h"
#include "log.h"

static qtch::Logger::ptr logger = QTCH_LOG_NAME("system");

namespace qtch{

ConfigVarBase::ptr Config::LookUpBase(const std::string name){
    MutexType::ReadLock lock(getMutex());
    auto it = Config::GetDatas().find(name);
    return it != GetDatas().end() ? it->second : nullptr; 
}

void Config::LoadConfigDir(const std::string path){
    std::string absoultPath = EnvMgr::GetInstance()->getAbsolutePath(path);
    if(!FSUtil::MkDir(absoultPath)){
        QTCH_LOG_ERROR(logger) << "load Config Folder path " <<absoultPath<< " faile";
        return;
    }
    std::vector<std::string> files;
    FSUtil::listAllFiles(files,absoultPath,".yml");
    for(auto it = files.begin(); it != files.end(); ++it){
        LoadYamlFile(*it);
    }
    

}

void Config::LoadYamlFile(const std::string filePath){
    if(!FSUtil::isFile(filePath)){
        QTCH_LOG_ERROR(logger) << "load Config file " <<filePath<< " faile";
        return;
    }
    QTCH_LOG_DEBUG(logger) << "load yaml file:" <<filePath;
    std::list<std::pair<std::string, YAML::Node> > save;
    YAML::Node node = YAML::LoadFile(filePath);
    ListAllMember("",node,save);
    for(auto it = save.begin(); it != save.end(); ++it){
        ConfigVarBase::ptr base = LookUpBase(it->first);
        if(base){
            MutexType::WriteLock lock(getMutex());
            if(it->second.IsScalar()){
                base->fromString(it->second.as<std::string>());
            }
            else{
                std::stringstream ss;
                ss << it->second;
                base->fromString(ss.str());
            }
        } 
    }
}

void Config::ListAllMember(std::string prefix,YAML::Node node,std::list<std::pair<std::string, YAML::Node> >& save){
    std::transform(prefix.begin(),prefix.end(),prefix.begin(),::tolower);
    if(prefix.find_first_not_of("abcdefghijklmnopqrstuvwxyz_.0123456789")!=std::string::npos){
        QTCH_LOG_ERROR(logger) << "listAllMember find illegal prefix " <<prefix;
        return;
    }
    save.push_back(std::make_pair(prefix,node));
    if(node.IsMap()){
        for(auto it = node.begin(); it != node.end(); ++it){
            ListAllMember((prefix.empty()? prefix:prefix+".")+it->first.as<std::string>(), it->second, save);
        }
    }
}







}